using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml;
using System.Windows.Controls;
using MapSurface.WidgetsProperties;
using MapSurface.UIModelElement;
using System.Windows.Markup;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;


namespace MapSurface.AssemblyReflexion
{
    public class AssemblyReflexion
    {
        #region Properties
        private Assembly _widgets = null;

        public Assembly Widgets
        {
            get { return _widgets; }
            set { _widgets = value; }
        }
        private Assembly _standard = null;

        public Assembly Standard
        {
            get { return _standard; }
            set { _standard = value; }
        }
        private Assembly _presentation = null;

        public Assembly Presentation
        {
            get { return _presentation; }
            set { _presentation = value; }
        }
        private List<Delegate> _selectEventHandler = null;

        public List<Delegate> SelectEventHandler
        {
            get {
                if (_selectEventHandler == null)
                    _selectEventHandler = new List<Delegate>(); 
                return _selectEventHandler; }
            set { _selectEventHandler = value; }
        }
        private Object _context = null;

        public Object Context
        {
            get { return _context; }
            set { _context = value; }
        }

        private List<RoutedEvent> _routedEvent = null;

        public List<RoutedEvent> RoutedEvent
        {
            get {
                if (_routedEvent == null)
                    _routedEvent = new List<RoutedEvent>();
                return _routedEvent;
            }
            set { _routedEvent = value; }
        }
        private static int itemId=0;
        #endregion
        
        #region Instances
        public AssemblyReflexion(string dllDir,List<Delegate> selectHandler)
        {

            RoutedEvent.Add(Microsoft.Surface.Presentation.Contacts.ContactTapGestureEvent);
            SelectEventHandler = selectHandler;

            _widgets = System.Reflection.Assembly.LoadFrom(dllDir + @"Microsoft.Surface.Presentation.dll");
            _standard = System.Reflection.Assembly.LoadFrom(dllDir + @"PresentationFramework.dll");
         }
        private void getInstanceElement(ref string widgetName, ref Object element)
        {
             if(widgetName.CompareTo("Page")==0)
                widgetName="SurfaceWindow";
            if (_widgets != null)
            {
                try
                {
                    if (widgetName.StartsWith("s:"))
                    {
                        string name = widgetName.Substring(2);
                        widgetName = name;
                    }
                    Type type = _widgets.GetType("Microsoft.Surface.Presentation.Controls." + widgetName);
                    if (type != null)
                        element = Activator.CreateInstance(type);
                    else
                    {
                        type = _standard.GetType("System.Windows.Controls." + widgetName);
                        if (type == null)
                            type = _standard.GetType("System.Windows.Shapes." + widgetName);
                        if (type != null)
                            element = Activator.CreateInstance(type);
 
                    }
                    if(element!=null)
                    for (int i = 0; i < _routedEvent.Count; i++)
                    {
                        try
                        {
                            ((System.Windows.UIElement)element).AddHandler(_routedEvent[i], _selectEventHandler[i]);
                        }
                        catch (Exception)
                        {
                            ((FrameworkElement)element).AddHandler(_routedEvent[i], _selectEventHandler[i]);
                        }
                    }



                }
                catch (Exception e)
                {
#if DEBUG
                    Console.WriteLine("[DEBUG]: getInstanceElement " + e.Message);
#endif
                }
            }
        }    
        public Object getInstance(string widgetName,   MapSurface.UIModelElement.UIElement current)
        {
            Object element = null;
            getInstanceElement(ref widgetName, ref element);
            if (element != null)
            {
                if (current.WidgetType != null && current.WidgetType.ContainsWidgets != null)
                {
                    object item=null;
                    string name=current.WidgetType.ContainsWidgets.Name;
                    getInstanceElement(ref name,ref item);
                    if (((Container)current).Contains != null && ((Container)current).Contains.Count > 0)
                        item = setDefaultValue(item, ((Container)current).Contains[0]);
                    else
                        item = setDefaultValue(item, current);
                    if (((Container)current).Contains != null && ((Container)current).Contains.Count>0)
                        item=setAttributes(item, ((Container)current).Contains[0]);
                    setAttribute(ref item, "Name", "item"+itemId++);
                    Property p =current.WidgetType.ContainsWidgets.getContentProperty();
                    if(p!=null)
                        setAttribute(ref item,p.Name,getObjectAttribute(item,"Name"));
                    element = addChild(element, item);
                }
                element = setAttributes(element, current);
                element = setEvents(element, current, _routedEvent, SelectEventHandler,_context);
                element = setEventsSelect(element,  _context);
                setDefaultValue(element, current);
                setAttribute(ref element, "Name", current.Name);

            }
            return element;
        }
        public Object getInstance(Widget widget)
        {
            Object element = null;
            string name=widget.Name;
            getInstanceElement(ref name, ref element);
            if (element != null)
            {
                if (widget.ContainsWidgets != null)
                {
                    object item = null;
                    name = widget.ContainsWidgets.Name;
                    getInstanceElement(ref name, ref item);
                    item = setDefaultValue(item,widget);
                    setAttribute(ref item, "Name", "item"+ itemId++);
                    element = addChild(element, item);
                }
                element = setEventsSelect(element,   _context);
                element = setDefaultValue(element,widget);
            }
            return element;
        }
        public Object getInstance(object instance)
        {
            Object element = null;
            string name = instance.GetType().Name;
            getInstanceElement(ref name, ref element);
            if (element != null)
            {
                foreach (PropertyInfo pi in instance.GetType().GetProperties())
                {
                    if (pi.CanRead && !pi.Name.Contains("Children") && pi.Name.CompareTo("Item")!=0)
                    {
                        setAttribute(ref element, pi.Name, getObjectAttribute(instance, pi.Name));
                    }
                }
            }
            return element;
        }

        #endregion
        
        #region Handler Setters
        private Object setEventsSelect(Object element, Object context)
        {
            try
            {
                //ScatterManipulationDelta="handler"
                setHandler(element, "Click", context, "handler");
                setHandler(element, "ContactDown", context, "handler");
                setHandler(element, "SizeChanged", context, "handler");
                setHandler(element, "ScatterManipulationDelta", context, "handler");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);

            }
            return element;

        }
        public void setHandler( Object instance, String evenName, Object context, String handler)
        {
            try
            {
                Type t = instance.GetType();
                System.Reflection.MethodInfo mi = context.GetType().GetMethod(handler);
                Type t2 = t.GetEvent(evenName).EventHandlerType;
                if (t2 != null)
                {
                    var d = EventHandler.CreateDelegate(t2, context, mi);
                    t.GetEvent(evenName).AddEventHandler(instance, d);
                }

            }catch(Exception e)
            {
#if DEBUG
                Console.WriteLine("[DEBUG] setHandler " + e.Message);   
#endif
            }
        }
        #endregion
        
        #region Attributs Setters
        public Object setAttributes(Object element, UIModelElement.UIElement node)
        {
            ParseValue p = new ParseValue();
            Type type = element.GetType();
            PropertyInfo pi;
            if (node.Properties!=null&& node.Properties.Count != 0)
            {
                foreach (UIModelElement.Property att in node.Properties)
                {
                    try
                    {
                        pi = type.GetProperty(att.Name);
                        if (att.Name.CompareTo("Name") == 0 && (att.Value == null || att.Value.Length<1))
                            att.Value = node.Name;
                        if (pi != null )
                        {
                            MethodInfo mi = pi.GetSetMethod(true);
                            object[] param = null;
                            if (p.IsDouble(att.Value))
                                param = new object[] { p.parseStrToDouble(att.Value) };
                            else if (p.isMargin(att.Value))
                                param = new object[] { p.parseToMargin(att.Value) };
                            else if (p.isBoolean(att.Value))
                                param = new object[] { p.parseToBoolean(att.Value) };
                            else if (att.Name.CompareTo("Visibility") == 0)
                                param = new object[] { p.parseToVisibility(att.Value) };
                            else if (p.isBrush(att.Value))
                                param = new object[] { p.parseToBrush(att.Value) };
                            else
                                param = new object[] { att.Value.ToString() };
                            if (mi != null)
                                mi.Invoke(element, param);
                        }
                    }
                    catch (Exception e)
                    {
#if DEBUG
                        Console.WriteLine("[DEBUG] setAttributes " + e.StackTrace);
#endif

                    }
                }
            }

            return element;
        }
        public Object setAttributes(Object element, UIModelElement.Container node)
        {
            ParseValue p = new ParseValue();
            Type type = element.GetType();
            PropertyInfo pi;
            if (node.Properties.Count != 0)
            {
                foreach (UIModelElement.Property att in node.Properties)
                {
                    try
                    {
                        pi = type.GetProperty(att.Name);
                        if (pi != null)
                        {
                            MethodInfo mi = pi.GetSetMethod(true);
                            object[] param = null;
                            if (p.IsDouble(att.Value))
                                param = new object[] { p.parseStrToDouble(att.Value) };
                            else if (p.isMargin(att.Value))
                                param = new object[] { p.parseToMargin(att.Value) };
                            else if (p.isBoolean(att.Value))
                                param = new object[] { p.parseToBoolean(att.Value) };
                            else if (att.Name.CompareTo("Visibility") == 0)
                                param = new object[] { p.parseToVisibility(att.Value) };
                            else if (p.isBrush(att.Value))
                                param = new object[] { p.parseToBrush(att.Value) };
                            else
                                param = new object[] { att.Value.ToString() };
                            if (mi != null)
                                mi.Invoke(element, param);
                        }
                    }
                    catch (Exception e)
                    {
#if DEBUG
                        Console.WriteLine("[DEBUG] setAttributes " + e.StackTrace);
#endif
                    }
                }

            }
           // pi = type.GetProperty("Content");
            PropertyInfo pname = type.GetProperty("Name");
           // if (pi == null)
            pi = type.GetProperty("Text");
            if (pi != null )
            {

                MethodInfo mi = pi.GetSetMethod(true);
                object[] param = new object[] { node.Name};
                if (string.Compare((String)param[0], "") != 0)
                    mi.Invoke(element, param);
            }
            if (pname != null)
            {

                MethodInfo mi = pname.GetSetMethod(true);
                object[] param = new object[] { node.Name };
                if (string.Compare((String)param[0], "") != 0)
                    mi.Invoke(element, param);
            }

            //Console.Out.WriteLine(XamlWriter.Save(element));
            return element;
        }
        public String getAttribute(Object element,string attibuteName)
        {
            String value = "";
            try
            {
                object o = null;
                Type type = element.GetType();
                PropertyInfo pi = type.GetProperty(attibuteName);
                if (pi != null)
                 {
                        MethodInfo [] mi = pi.GetAccessors();
                        object[] param = null;
                        if (mi != null)
                            o = pi.GetValue(element, param);
                                //mi[0].Invoke(element, param);
                        if (o != null)
                            value = o.ToString();

                    }
                }
            catch (Exception)
            {
                //;
            }
            return value;
        }
        public object getObjectAttribute(Object element, string attibuteName)
        {
            try
            {
                object o = null;
                Type type = element.GetType();
                PropertyInfo pi = type.GetProperty(attibuteName);
                if (pi != null)
                {
                    MethodInfo[] mi = pi.GetAccessors();
                    object[] param = null;
                    if (mi != null)
                        o = pi.GetValue(element, param);
                    //mi[0].Invoke(element, param);
                    if (o != null)
                        return o;

                }
            }
            catch (Exception)
            {
                //;
            }
            return null;
        }

        public void setAttribute(ref Object element, string attibuteName, object value)
        {
            try
            {
                Type type = element.GetType();
                PropertyInfo pi = type.GetProperty(attibuteName);
                if (pi != null)
                {
                    object[] param = {value};
                    MethodInfo mi = pi.GetSetMethod();
                    //pi.SetValue(element, value, param);
                    if(mi!=null)
                        mi.Invoke(element, param);


                }
            }
            catch (Exception )
            {
                //;
            }
        }

        public void setAttribute(ref Object element, Widget wt, Widget ws,object instance)
        {
            foreach (Property pi in wt.Properties)
            {
                foreach(Property pt in ws.Properties)
                    if(pt.isRenderingProperty() && pi.isRenderingProperty())
                    {                     
                        setAttribute(ref element, pi.Name, getObjectAttribute(instance,pt.Name));
                    }
            }
        }
        public void setAttribute(ref Object element,object oldobject)
        {
            try
            {
                Type type = oldobject.GetType();
                PropertyInfo[] pi = type.GetProperties();
                if (pi != null)
                {
                    foreach (PropertyInfo p in pi)
                    {
                        MethodInfo mig = p.GetGetMethod();
                        if (mig != null)
                        {
                            object value = mig.Invoke(oldobject, null);
                            object[] param = { value };
                            MethodInfo mi = p.GetSetMethod(true);
                            //pi.SetValue(element, value, param);
                            if (mi != null)
                                mi.Invoke(element, param);
                        }
                    }

                }
            }
            catch (Exception)
            {
                //;
            }
        }
        
        public Type getType(String widgetName)
        {
            return _widgets.GetType("Microsoft.Surface.Presentation.Controls." + widgetName);
        }
        public void displayProperties(Object container, Object uiElement)
        {
            PropertyInfo[] pi = uiElement.GetType().GetProperties();
            foreach(PropertyInfo i in pi)
            {
                Object value=i.GetValue(uiElement,null);

                if (value != null  && value.ToString().CompareTo("False")==0)
                {
                    ListBoxItem lbi = new ListBoxItem();
                    lbi.Content = i.Name + "  " + value.ToString();
                    ((ListBox)container).Items.Add(lbi);
                }
            }
        }       
        private Object setProperty(Type type,String name, Object value, Object instance)
        {
            PropertyInfo pi = type.GetProperty(name);
            if (pi != null)
                pi.SetValue(instance,value, null);
           return instance;
        }
        public Object addChild(Object objectUI, Object obj)
        {
            if (obj != null)
            {
                if (objectUI != null)
                {
                    if (isItemControl(objectUI))
                    {
                        ((ItemsControl)objectUI).Items.Add(obj);

                    }
                    else if (isPanel(objectUI))
                    {
                        ((Panel)objectUI).Children.Add((System.Windows.UIElement)obj);
                        int n = ((Panel)objectUI).Children.Count;
                        if (n > 1)
                            defineLayout((Panel)objectUI);
                    }
                    else if (isContentControl(objectUI))
                        ((ContentControl)objectUI).Content = obj;
                    else if (isViewBox(objectUI))
                    {
                        ((Decorator)objectUI).Child = (System.Windows.UIElement)obj;
                    }
                }
                else
                    objectUI = obj;
                if (objectUI.GetType().Name.CompareTo("ScatterViewItem") == 0)
                {

                    ((ScatterViewItem)objectUI).Height = ((FrameworkElement)obj).RenderSize.Height + 5;
                    ((ScatterViewItem)objectUI).Width = ((FrameworkElement)obj).Width + 5;
                    ((ScatterViewItem)objectUI).Margin = new Thickness(10);
                }
            }

            return objectUI;
        }
        public Object addChilds(Object objectUI, List<Object> obj)
        {
            if (obj != null && obj.Count>0)
                if (objectUI != null)
                {
                    if (isItemControl(objectUI))
                        foreach (object o in obj)
                        {
                            if (o != null)
                                ((ItemsControl)objectUI).Items.Add(o);
                        }
                    else if (isPanel(objectUI))
                                foreach (object o in obj)
                                {
                                    if (o != null)
                                        ((Panel)objectUI).Children.Add((System.Windows.UIElement)o);
                                }
                    else if (isContentControl(objectUI))
                                foreach (object o in obj)
                                {
                                    if (o != null)
                                        ((ContentControl)objectUI).Content = o;
                                }
                    else if (isViewBox(objectUI))
                    {
                        if(((FrameworkElement)obj[0]).Parent==null)
                         ((Decorator)objectUI).Child = (System.Windows.UIElement)obj[0];
                    }
                }
            return objectUI;
        }

        private Object setEvents(Object element, UIModelElement.UIElement current, List<RoutedEvent> _routedEvent, List<Delegate> _selectEventHandler, Object context)
        {
            if (current.Events != null)
                foreach (Event e in current.Events)
                {
                    try
                    {
                        setHandler(element, e.Name, context, "handler");

                    }
                    catch (Exception)
                    {

                    }
                }

            return element;

        }

        #endregion
        
        #region Finder methods

        public Border setBorder(System.Windows.UIElement neested)
        {
            Border border = new Border();
            border.BorderBrush = Brushes.Black;
            border.BorderThickness = new Thickness(3);
            border.Name = "SelectBorder";
            Object s = getAttribute(neested, "RenderSize");
            if (s != null)
            {
                string[] size = s.ToString().Split(';');
                border.Width = Double.Parse(size[0]) + 3;
                border.Height = Double.Parse(size[1]) + 3;
            }
            if (border.Child == null)
                border.Child = neested;
            border.Background = Brushes.Blue;
            return border;
        }
        public Boolean isItemControl(Object element)
        {
            try
            {

                ItemsControl obj = (ItemsControl)element;
                return true;
            }
            catch (InvalidCastException )
            {
            }
            return false;
        }
        public Boolean isPanel(Object element)
        {
            try
            {
                Panel p = (Panel)element;
                return true;
            }
            catch (InvalidCastException )
            {

            }
            return false;
        }
        public Boolean isContentControl(Object element)
        {
            try
            {
                ContentControl c = (ContentControl)element;
                return true;
            }
            catch (InvalidCastException  )
            {
            }
            return false;
        }
        public Boolean isViewBox(Object element)
        {
            try
            {
                Decorator c = (Decorator)element;
                return true;
            }
            catch (InvalidCastException)
            {
            }
            return false;

        }
        public List<Object> getChild(Object element)
        {
          
            List<Object> childs = new List<object>();
            if (element != null)
            {
                if (isItemControl(element))
                {
                    foreach (object o in ((ItemsControl)element).Items)
                        childs.Add(o);
                }
                else if (isPanel(element))
                {
                    try
                    {
                        foreach (object o in ((Panel)element).Children)
                            childs.Add(o);
                    }
                    catch (Exception)
                    {
                    }
                }
                else if (isViewBox(element) && ((Decorator)element).Child!=null)
                {
                    childs.Add(((Decorator)element).Child);
                }
                else if (isContentControl(element) && ((ContentControl)element).Content!=null)
                {
                    try
                    {
                        childs.Add((FrameworkElement)((ContentControl)element).Content);
                    }
                    catch (InvalidCastException)
                    {
                    }
                }
            }
            return childs;
        }
        public void removeChild(ref Object element,  Object child)
        {
            if (((FrameworkElement)child).Parent != null && ((FrameworkElement)child).Parent.GetHashCode()==element.GetHashCode())
            {
                element = removeVisualChid(((FrameworkElement)child).Parent, child);
            }
            if (isItemControl(element))
            {
                ((ItemsControl)element).Items.Remove(child);
            }
            else if (isPanel(element))
            {
                try
                {
                    ((Panel)element).Children.Remove((System.Windows.UIElement)child);
                }
                catch (Exception)
                {
                }
            }
            else if(isViewBox(element))
            {
                ((Decorator)element).Child = null;
            }
            else if (isContentControl(element))
            {
                ((ContentControl)element).Content = null;
            }

        }
        private List<Object> getVisualChild(Object element)
        {
            List<Object> childs= new List<object>();
            if (element != null)
            {
                try
                {
                    Type t = ((Visual)element).GetType();
                    System.Reflection.MethodInfo mi = t.GetMethod("VisualChildrenCount", BindingFlags.Instance | BindingFlags.NonPublic);
                    object child = null;
                    Object[] param = { child };
                    int n=0;
                    if (mi != null)
                        n= (int)mi.Invoke(element, param);
                    if (n > 0)
                    {
                        for (int i = 0; i < n; i++)
                        {
                            System.Reflection.MethodInfo mi1 = t.GetMethod("GetVisualChild", BindingFlags.Instance | BindingFlags.NonPublic);
                             Object[] param1 = { i };
                             object ch = null;
                             if (mi1 != null)
                             {
                                 ch = (int)mi1.Invoke(element, param1);
                                 childs.Add(ch);
                             }
                        }
                    }
                }
                catch (Exception e)
                {
#if DEBUG
                    Console.Out.WriteLine("[DEBUG] removeChild " + e.Message);
#endif
                }
            }
            return childs;

        }
        public Object removeVisualChid(Object element, Object child)
        {
            if (element!=null)
            {
                List<object> childs = getVisualChild(element);
                foreach (object o in childs)
                {
                    if(o.GetHashCode()==child.GetHashCode())
                    try
                    {
                        Type t = element.GetType();
                        System.Reflection.MethodInfo mi = t.GetMethod("RemoveVisualChild", BindingFlags.Instance | BindingFlags.NonPublic);
                        Object[] param = { child };
                        if (mi != null)
                            mi.Invoke(element, param);
                    }
                    catch (Exception e)
                    {
#if DEBUG
                        Console.Out.WriteLine("[DEBUG] removeChild " + e.Message);
#endif
                    }
                }
            }
            return element;

        }
 
        public Boolean isImage(Object element)
        {
            if (element != null)
                return element.GetType().Name.Contains("Image");
            return false;
        }
        public Object setDefaultValue(Object element, MapSurface.UIModelElement.UIElement  uielement)
        {
            if(isImage(element))
            {
                Type type=element.GetType();
                BitmapImage bi3 = new BitmapImage();
                bi3.BeginInit();
                bi3.UriSource = new Uri(".\\Resources\\icon.PNG", UriKind.Relative);
                bi3.EndInit();
                setProperty(type, "Source", bi3, element);
            }
            FlowDirection f= FlowDirection.LeftToRight;
            setAttribute(ref element,"FlowDirection",f);
            Thickness t = new Thickness(3);
            setAttribute(ref element, "Margin", t);
            string content = getContentProperty(uielement);
            if (content != null)
            {
                string value = getAttribute(element, content);
                if(value==null || value.Length<1)
                    setAttribute(ref element, content, getAttribute(element,"Name"));
            }
            if (element.GetType().Name.CompareTo("ScatterView") == 0)
            {
                ((ScatterView)element).Height = 300;
                ((ScatterView)element).Width = 400;
            }
            return element;
        }
        public Object setDefaultValue(Object element, Widget  uielement)
        {
            if(isImage(element))
            {
                Type type=element.GetType();
                BitmapImage bi3 = new BitmapImage();
                bi3.BeginInit();
                bi3.UriSource = new Uri(".\\Resources\\icon.PNG", UriKind.Relative);
                bi3.EndInit();
                setProperty(type, "Source", bi3, element);
            }
            FlowDirection f= FlowDirection.LeftToRight;
            setAttribute(ref element,"FlowDirection",f);
            Thickness t = new Thickness(3);
            setAttribute(ref element, "Margin", t);
            string content = getContentProperty(uielement);
            if (content != null)
            {
                string value = getAttribute(element, content);
                if(value==null || value.Length<1)
                    setAttribute(ref element, content, getAttribute(element,"Name"));
            }
            if (uielement.Name.CompareTo("ScatterView")==0 && element.GetType().Name.CompareTo("ScatterView") == 0)
            {
                ((ScatterView)element).Height=300;
                ((ScatterView)element).Width=400;
            }

            return element;
        }

        private string getContentProperty(MapSurface.UIModelElement.UIElement element)
        {
            if (element.Properties != null && element.Properties.Count > 0)
                foreach (Property p in element.Properties)
                    if (p.Node != null && p.Node.HasChildNodes)
                        return p.Name;
            return null;
        }
        private string getContentProperty(Widget element)
        {
            if (element.Properties != null && element.Properties.Count > 0)
                foreach (Property p in element.Properties)
                    if (p.Node != null && p.Node.HasChildNodes)
                        return p.Name;
            return null;
        }

        #endregion
        
        #region Edit Instance
        public List<object> RemoveChid(ref object instance)
        {
            List<object> lchild = new List<object>();
            if(instance!=null)
            {
                lchild = getChild(instance);
                if(lchild!=null && lchild.Count>0)
                    foreach (object o in lchild)
                    {
                        try
                        {
                            removeChild(ref instance, o);
                        }
                        catch (Exception)
                        {
                        }
                    }

            }
            return lchild;
        }

        #endregion
        
        #region Update Layout
        private object defineLayout(Panel parent)
        {
            int marg = 5;
            Thickness t = new Thickness(marg, marg, marg, marg);
            int n = parent.Children.Count;
            if (n == 0)
                return parent;
            double maxw=getMaxWidth((Grid)parent);
  
            double w = maxw;
            double h = getMaxHeight((Grid)parent);
            double maxh = h;
            double w1 = 0;
            double h1 = h;
            int li = 0, li1 = 0, ci = 0, ci1 = 0;
            for (int i = 0; i < n; i++)
            {
                li = i / 2;
                ci = i % 2;
                if (i > 0)
                {
                    if (li == li1 && ci != ci1)
                    {
                        w = w + maxw;
                        w1 = maxw;
                    }
                    if (ci == 0)
                    {
                        w = 0; w1 = 0 + marg;
                    }
                    if (ci == ci1 && li != li1)
                    {
                        h += maxh;
                        h1 = maxh;
                    }
                    if (li == 0)
                    {
                        h = 0;
                        h1 = 0;
                    }
                    li1 = li;
                    ci1 = ci;
                    t = new Thickness(marg * 2 * ci + w, marg * 2 * li + h, marg, marg);
                    ((FrameworkElement)parent.Children[i]).Margin = t;
                    Thickness t1 = ((FrameworkElement)parent.Children[i - 1]).Margin;
                    ((FrameworkElement)parent.Children[i - 1]).Margin = new Thickness(t1.Left, t1.Top, t1.Right + w1, t1.Bottom + h1);

                }
                else
                {
                    t = new Thickness(marg, marg, marg, marg);
                    ((FrameworkElement)parent.Children[i]).Margin = t;

                }
            }
            return parent;
        }

        private object defineLayout(ItemsControl parent)
        {
            int marg = 5;
            Thickness t = new Thickness(marg, marg, marg, marg);
            int n = parent.Items.Count;
            if (n == 0)
                return parent;
            double w = 0;
            double h = 0;
            double w1 = 0;
            double h1 = 0;
            int li = 0, li1 = 0, ci = 0, ci1 = 0;
            for (int i = 0; i < n; i++)
            {
                li = i / 2;
                ci = i % 2;
                if (i > 0)
                {
                    if (li == li1 && ci != ci1)
                    {
                        w += ((FrameworkElement)parent.Items[i - 1]).RenderSize.Width;
                        w1 = ((FrameworkElement)parent.Items[i]).RenderSize.Width + 2;
                    }
                    if (ci == 0)
                    {
                        w = 0; w1 = 0 + marg;
                    }
                    if (ci == ci1 && li != li1)
                    {
                        h += ((FrameworkElement)parent.Items[i - 1]).RenderSize.Height;
                        h1 = ((FrameworkElement)parent.Items[i]).RenderSize.Height + 2 * marg;
                    }
                    if (li == 0)
                    {
                        h = 0;
                        h1 = 0;
                    }
                    li1 = li;
                    ci1 = ci;
                    t = new Thickness(marg * 2 * ci + w, marg * 2 * li + h, marg, marg);
                    ((FrameworkElement)parent.Items[i]).Margin = t;
                    Thickness t1 = ((FrameworkElement)parent.Items[i - 1]).Margin;
                    ((FrameworkElement)parent.Items[i - 1]).Margin = new Thickness(t1.Left, t1.Top, t1.Right + w1, t1.Bottom + h1);

                }
                else
                {
                    t = new Thickness(marg, marg, marg, marg);
                    ((FrameworkElement)parent.Items[i]).Margin = t;

                }
            }
            return parent;
        }

        private object defineLayout(Decorator parent)
        {
            int marg = 5;
            Thickness t = new Thickness(marg, marg, marg, marg);
            t = new Thickness(marg, marg, marg, marg);
            if((FrameworkElement)parent.Child!=null)
              ((FrameworkElement)parent.Child).Margin = t;
            return parent;
        }

        public object defineLayout(object parent)
        {
            if (isItemControl(parent))
                return defineLayout((ItemsControl)parent);
            else if (isPanel(parent))
                return defineLayout((Panel)parent);
            else if (isViewBox(parent))
                return defineLayout((Decorator)parent);
            return parent;
        }
        private double getMaxWidth(Grid parent)
        {
            double width = 100;
            if (parent.Children!=null && parent.Children.Count>0)
                foreach (System.Windows.UIElement e in parent.Children)
                {
                    if (((FrameworkElement)e).Width.CompareTo(double.NaN) != 0)
                    {
                        if (((FrameworkElement)e).Width > width)
                            width = ((FrameworkElement)e).Width;
                    }
                    else if (((FrameworkElement)e).ActualWidth > width)
                        width = ((FrameworkElement)e).ActualWidth;
                }
            return width;
        }
        private double getMaxHeight(Grid parent)
        {
            double height = 50;
            if (parent.Children != null && parent.Children.Count > 0)
                foreach (System.Windows.UIElement e in parent.Children)
                {
                    if (((FrameworkElement)e).Height.CompareTo(double.NaN) != 0)
                    {
                        if (((FrameworkElement)e).Height > height)
                            height = ((FrameworkElement)e).Width;
                    }
                    else if (((FrameworkElement)e).ActualHeight > height)
                        height = ((FrameworkElement)e).ActualHeight;
                }
            return height;
        }
  
        #endregion

        public bool deleteXamlObject(ref object root, object instance)
        {
            bool ret= false;
            List<object> list = getChild(root);
            if (list != null)
                foreach (object o in list)
                    if (o.GetHashCode() == instance.GetHashCode())
                    {
                        if (list.Count == 1)
                            ret= true;
                        removeChild(ref root, o);
                    }
                    else
                    {
                        object ob = o;
                        if(deleteXamlObject(ref ob, instance))
                            removeChild(ref root,o);
                    }
            return ret;
        }

        public void addEvent(ref object instance, Event e, object context)
        {



        }
    }
}
